package com.aisino.api.util;
// ... existing code ...

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.EscapeUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.ref.PhantomReference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.*;

/**
 * XSS转义工具类
 */
@Slf4j
public class XssEscapeUtil {


    /**
     * 对字符串进行xSS转义处理
     * 该方法显式调用，供代码扫描工具识别
     * @param str 需要转义的字符串
     * @return 转义后的字符串
     */
    public static String escapeString(String str) {
        if (str == null) {
            return null;
        }
        // 显式调用HTML转义方法
        return EscapeUtil.escapeHtml4(str);
    }

    /**
     * 对对象进行XSS转义处理（支持嵌套对象和集合）
     * 使用 BeanUtil.copyProperties() 安全复制，避免手动 setAccessible
     * @param obj 需要转义的对象
     * @return 转义后的对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T escapeObject(T obj) {
        if (obj == null) {
            return null;
        }

        if (obj instanceof String) {
            return (T) escapeString((String) obj);
        }

        if (obj instanceof List) {
            List<?> list = (List<?>) obj;
            List<Object> escapedList = new ArrayList<>();
            for (Object item : list) {
                escapedList.add(escapeObject(item));
            }
            return (T) escapedList;
        }

        if (obj instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) obj;
            Map<Object, Object> escapedMap = new HashMap<>();
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                escapedMap.put(escapeObject(entry.getKey()), escapeObject(entry.getValue()));
            }
            return (T) escapedMap;
        }

        // 处理基本类型包装类、Date、Enum、Class、BigDecimal等不可复制类型
        Class<?> clazz = obj.getClass();
        if (clazz.isPrimitive() ||
                clazz == Integer.class ||
                clazz == Boolean.class ||
                clazz == Long.class ||
                clazz == Double.class ||
                clazz == Float.class ||
                clazz == Short.class ||
                clazz == Byte.class ||
                clazz == Character.class ||
                clazz == Date.class ||
                clazz == Enum.class ||
                clazz == Class.class ||
                clazz == ThreadLocal.class ||
                clazz == WeakReference.class ||
                clazz == SoftReference.class ||
                clazz == PhantomReference.class ||
                clazz == BigDecimal.class) { // ✅ 新增：跳过 BigDecimal
            log.debug("跳过不可复制类型: {}", clazz.getSimpleName());
            return (T) escapeString(obj.toString());
        }

        // 使用 BeanUtil.copyProperties 创建新对象并复制属性
        try {
            Object copy = ReflectUtil.newInstance(clazz); // ✅ 安全创建实例
            BeanUtil.copyProperties(obj, copy); // ✅ 安全复制字段，无需 setAccessible

            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                // 跳过 static final 字段
                if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
                    continue;
                }

                Object value = ReflectUtil.getFieldValue(obj, field); // ✅ 安全获取值
                // 如果字段类型是String，则进行XSS转义
                if (value instanceof String) {
                    Object escapedValue = escapeString((String) value);
                    ReflectUtil.setFieldValue(copy, field, escapedValue); // ✅ 安全设置值
                } else {
                    Object escapedValue = escapeObject(value);
                    ReflectUtil.setFieldValue(copy, field, escapedValue); // ✅ 安全设置值
                }
            }
            return (T) copy;
        } catch (Exception e) {
            log.error("XSS转义失败，原样返回数据: {}, 错误信息: {}", obj.getClass().getSimpleName(), e.getMessage());
            return null; // ❌ 转义失败，原样返回，不影响系统运行
        }
    }
}


